﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utilities.Common;


namespace DataBaseManager
{
    public class DifferentialUpdate<T> where T:new ()
    {
        T secondary;
        T original;
        ClassInfo info;

        public void BeginEdit(T obj)
        {
            info = ClassInfoCache.GetClassInfo(obj);
            object auxOriginal;
            object auxSecondary;
            original = obj;
            secondary = new T();//creo una copia del objeto
            foreach (var item in info.Properties)//copio cada una de las propiedades
            {
                if (item.IsClass)
                {                   
                    auxOriginal=item.GetValue(original);//extraigo la propiedad que quiero copiar (que es un objeto)

                    if (auxOriginal != null)
                    {
                        auxSecondary = item.ClassInfo.GetNew();//creo una nueva instancia y le asigno los valores a las propiedades

                        foreach (var prop in item.ClassInfo.Properties)
                        {
                            prop.SetValue(auxSecondary, prop.GetValue(auxOriginal));
                        }
                        //ya copie los valores, ahira se lo asigno al objeto
                        item.SetValue(secondary, auxSecondary);
                    }
                    else
                    {
                        item.SetValue(secondary,(object) null);
                    }
                   
                }
                else
                {
                    item.SetValue(secondary, item.GetValue(obj));
                }
                
            }

        }
        public PropInfoManager GetDifferences()
        {
            object val1; object val2;
            PropInfoManager properties = new PropInfoManager();
            foreach (var item in info.Properties)//comparo cada propiedad con la que tenia en la copia
            {
#warning verificar esta comparacion
                
                //si son valores (int, string, etc) compara directamente los valores
                //si son objetos, compara por id
                val1 = item.GetValue(secondary, item.IsClass);
                val2 = item.GetValue(original, item.IsClass);
                if (val1 != null && val2 != null)
                {
                    if (!val1.Equals(val2) || item.IsId)//el id siempre lo agrego
                    {
                        properties.Add(item);
                    }
                }
                else
                {
                    //aca val es nulo, pero puede ser correcto valores nulos, por las dudas que haga el update
                    properties.Add(item);
                }

            }

            return properties;
        }
        /// <summary>
        /// Guarda solo las propiedades que se modificaron desde que se ejecuto la funcioon BeginEdit. Agrega el Id automaticamente.
        /// </summary>
        /// <param name="db"></param>
        /// <param name="t"></param>
        public void Save(Database db, TableName t)
        {
            db.Update(t, DataBaseHelper.BuildParameters(GetDifferences(), original));
        }

        /// <summary>
        /// Guarda solo las propiedades que se odificaron. Permite agregar manualmente mas propiedades.
        /// </summary>
        /// <param name="db"></param>
        /// <param name="t"></param>
        /// <param name="parameters"></param>
        public void Save(Database db, TableName t, ParameterManager parameters)
        {
#warning verificar que no se repitan los parametros
            db.Update(t, DataBaseHelper.BuildParameters(GetDifferences(), original));
        }
    }
}
